package org.example.controller;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import org.commonmark.node.Heading;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.text.TextContentRenderer;
import org.example.mapper.VulnMapper;
import org.example.pojo.BookMarks;
import org.example.pojo.VulnTempVO;
import org.example.pojo.Vulnerabilities;
import org.example.service.BookMarksService;
import org.example.utils.Loggable;
import org.example.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("/api/upload")
public class FileUploadController {
    @Value("${file.upload-dir}")
    private String uploadDir;
    @Autowired
    private BookMarksService bookMarksService;
    @Autowired
    private VulnMapper vulnMapper;
    @PostMapping
    public Result uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
            if (file.isEmpty()) {
                return Result.error("文件不能为空");
            }
            File dir = new File(uploadDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            String fileName = UUID.randomUUID().toString() + "_" + file.getOriginalFilename();
            Path path = Paths.get(uploadDir + fileName);
            Files.copy(file.getInputStream(), path);
            Map<String, String> obj = new HashMap<>();
            obj.put("url", "http://localhost:23108/images/"+fileName);
            return Result.success(obj);
    }
    @PostMapping("/bookmark")
    public Result uploadBookmark(@RequestParam("file") MultipartFile data, @RequestParam("userId") Integer userId) throws IOException {
        if (data.isEmpty()) {
            return Result.error("文件不能为空");
        }
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        Integer index = data.getOriginalFilename().lastIndexOf(".");
        String title = data.getOriginalFilename().substring(0, index);
        String fileName = UUID.randomUUID().toString() + "_" + data.getOriginalFilename();
        Path path = Paths.get(uploadDir + fileName);
        Files.copy(data.getInputStream(), path);
        String url = "http://localhost:23108/images/" + fileName;
        BookMarks bookMarks = new BookMarks();
        bookMarks.setUserId(userId);
        bookMarks.setTitle(title);
        bookMarks.setUrl(url);
        bookMarksService.addBookMarks(bookMarks);
        return Result.success();
    }
    @PostMapping("/vulntemplate")
    @Loggable(action = "导入漏洞模板")
    public Result uploadVulnTemplate(@RequestParam("file") MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        File dir = new File(uploadDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        Path path = Paths.get(uploadDir + UUID.randomUUID().toString() + "_" + file.getOriginalFilename());
        Files.copy(file.getInputStream(), path);
        Integer index = file.getOriginalFilename().lastIndexOf(".");
        // 模板名称
        String name = file.getOriginalFilename().substring(0, index);
        VulnTempVO vulnTempVO = new VulnTempVO();
        vulnTempVO.setName(name);
        vulnTempVO.setDescription(name);
        List<String> results = new ArrayList<>();
        try (ZipFile zipFile = new ZipFile(String.valueOf(path))) {
            List<FileHeader> fileHeaders = zipFile.getFileHeaders();
            int vulnNum = 0;
            for (FileHeader fileHeader : fileHeaders) {
                String fileName = fileHeader.getFileName();
                if (fileName.endsWith(".md")) {
                    String content = new String(zipFile.getInputStream(fileHeader).readAllBytes(), "UTF-8");
//                    Map<String, String> fields = parseMarkdown(content, vulnTempVO.getId(), name);
                    results.add(content);
                    vulnNum ++;
//                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(zipFile.getInputStream(fileHeader)))) {
//                        String line;
//                        while ((line = reader.readLine()) != null) {
//                            System.out.println(line);
//                        }
//                    }
                }
            }
            vulnTempVO.setVulnNum(vulnNum);
            vulnMapper.addVulnTemp(vulnTempVO);
            for (String content: results) {
                parseMarkdown(content, vulnTempVO.getId(), name);
            }
        }
        return Result.success();
    }
    private void parseMarkdown(String markdownContent, Integer tempId, String vulnType) {
        Parser parser = Parser.builder().build();
        Node document = parser.parse(markdownContent);
        Map<String, String> fields = new HashMap<>();
        String currentHeading = null;
        StringBuilder currentContent = new StringBuilder();
        boolean nameFlag = true;
        for (Node node = document.getFirstChild(); node != null; node = node.getNext()) {
            if (node instanceof Heading) {
                if (currentHeading != null) {
                    if (nameFlag) {
                        fields.put("漏洞名称", currentHeading);
                        nameFlag = false;
                    } else {
                        fields.put(currentHeading, currentContent.toString().trim());
                    }
                    currentContent.setLength(0);
                }
                currentHeading = extractText(node);
            } else {
                if (currentHeading != null) {
                    currentContent.append(extractText(node)).append("\n");
                }
            }
        }
        if (currentHeading != null) {
            fields.put(currentHeading, currentContent.toString().trim());
        }
        Vulnerabilities vuln = new Vulnerabilities();
        vuln.setTempId(tempId);
        Map<String, String> result = new HashMap<>();
        // 处理特定字段
        for (Map.Entry<String, String> entry : fields.entrySet()) {
            String key = entry.getKey();
            if (key.contains("漏洞名称")) {
                vuln.setVulnName(entry.getValue());
            }
            if (key.contains("漏洞描述")) {
                vuln.setDescription(entry.getValue());
            }
            if (key.contains("漏洞影响")) {
                vuln.setAffectedProduct(entry.getValue());
            }
            if (key.contains("修复")) {
                vuln.setSuggestion(entry.getValue());
            }
            if (key.contains("复现")) {
                vuln.setReference(entry.getValue());
            }
            if (key.contains("等级") || key.contains("级别")) {
                vuln.setSeverity(entry.getValue());
            }
        }
        vuln.setVulnType(vulnType);
        Random random = new Random();
        double randomValue = 0.0 + (10.0 - 0.0) * random.nextDouble();
        double roundedValue = Math.round(randomValue * 10) / 10.0;
        vuln.setBaseScore(String.valueOf(roundedValue));
        Date currentDate1 = new Date();
        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formattedDate1 = sdf1.format(currentDate1);
        vuln.setPublishTime(formattedDate1);
        vuln.setOrigin("用户导入");
        vulnMapper.insert(vuln);
    }

    private String extractText(Node node) {
        TextContentRenderer renderer = TextContentRenderer.builder().build();
        return renderer.render(node);
    }

    private String extractCveId(String description) {
        if (description != null) {
            int startIndex = description.indexOf("CVE-");
            if (startIndex != -1) {
                int endIndex = description.indexOf(" ", startIndex);
                if (endIndex == -1) {
                    endIndex = description.length();
                }
                return description.substring(startIndex, endIndex);
            }
        }
        return "";
    }
}
